package api

import (
	"context"
	"crypto/sha256"
	"encoding/hex"
	"errors"
	"fmt"
	"log"
	"strings"
	"time"

	"github.com/dgrijalva/jwt-go"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
)

// MongoUserService 使用MongoDB实现用户服务
type MongoUserService struct {
	usersCollection                 *mongo.Collection
	rolesCollection                 *mongo.Collection
	deviceDataCollection            *mongo.Collection
	devicePropertyConfigsCollection *mongo.Collection
	jwtSecret                       []byte
	tokenExpirationHours            int
}

// NewMongoUserService 创建一个新的MongoDB用户服务
func NewMongoUserService(mongoClient *mongo.Client, dbName string, jwtSecret string) (*MongoUserService, error) {
	// 检查MongoDB客户端
	if mongoClient == nil {
		return nil, errors.New("mongo client cannot be nil")
	}

	// 获取集合
	usersCollection := mongoClient.Database(dbName).Collection("users")
	rolesCollection := mongoClient.Database(dbName).Collection("roles")
	deviceDataCollection := mongoClient.Database(dbName).Collection("device_data")
	devicePropertyConfigsCollection := mongoClient.Database(dbName).Collection("device_property_configs")

	// 创建索引以提高查询性能
	_, err := usersCollection.Indexes().CreateMany(context.Background(), []mongo.IndexModel{
		{
			Keys:    bson.D{{Key: "username", Value: 1}},
			Options: options.Index().SetUnique(true),
		},
		{
			Keys:    bson.D{{Key: "email", Value: 1}},
			Options: options.Index().SetUnique(true),
		},
	})
	if err != nil {
		return nil, fmt.Errorf("failed to create indexes: %v", err)
	}

	//初始化一些默认角色权限（如果不存在）
	service := &MongoUserService{
		usersCollection:                 usersCollection,
		rolesCollection:                 rolesCollection,
		deviceDataCollection:            deviceDataCollection,
		devicePropertyConfigsCollection: devicePropertyConfigsCollection,
		jwtSecret:                       []byte(jwtSecret),
		tokenExpirationHours:            24, // 默认token有效期24小时
	}

	// 初始化默认角色
	service.initDefaultRoles()

	return service, nil
}

// 初始化默认角色
func (s *MongoUserService) initDefaultRoles() {
	// 管理员角色权限
	adminPerm := &RolePermission{
		Role: "admin",
		Permissions: []string{
			"read_device", "write_device", "delete_device",
			"read_user", "write_user", "delete_user",
			"manage_roles", "manage_system",
		},
	}

	// 操作员角色权限
	operatorPerm := &RolePermission{
		Role: "operator",
		Permissions: []string{
			"read_device", "write_device",
			"read_user",
		},
	}

	// 查看者角色权限
	viewerPerm := &RolePermission{
		Role: "viewer",
		Permissions: []string{
			"read_device",
			"read_user",
		},
	}

	// 保存默认角色
	for _, role := range []*RolePermission{adminPerm, operatorPerm, viewerPerm} {
		existingRole, _ := s.GetRolePermission(role.Role)
		if existingRole == nil {
			s.UpdateRolePermission(role)
		}
	}
}

// 哈希密码
func hashPassword(password string) string {
	hash := sha256.Sum256([]byte(password))
	return hex.EncodeToString(hash[:])
}

// 验证密码
func verifyPassword(password, hashedPassword string) bool {
	return hashPassword(password) == hashedPassword
}

// GenerateToken 生成JWT令牌
func (s *MongoUserService) GenerateToken(user *User) (string, error) {
	expirationTime := time.Now().Add(time.Duration(s.tokenExpirationHours) * time.Hour)

	claims := &jwt.StandardClaims{
		ExpiresAt: expirationTime.Unix(),
		IssuedAt:  time.Now().Unix(),
		Subject:   user.ID,
		Id:        user.ID,
	}

	// 创建token对象
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)

	// 签名并获取完整的编码后的字符串token
	tokenString, err := token.SignedString(s.jwtSecret)
	if err != nil {
		return "", err
	}

	return tokenString, nil
}

// ValidateToken 验证JWT令牌
func (s *MongoUserService) ValidateToken(tokenString string) (*User, error) {
	claims := &jwt.StandardClaims{}

	token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
		// 验证签名算法
		if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
			return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
		}
		return s.jwtSecret, nil
	})

	if err != nil || !token.Valid {
		return nil, errors.New("invalid or expired token")
	}

	// 根据用户ID获取用户信息
	return s.GetUserByID(claims.Subject)
}

// CreateUser 创建新用户
func (s *MongoUserService) CreateUser(user *User) error {
	// 检查必要字段
	if user.Username == "" || user.Password == "" || user.Email == "" {
		return errors.New("username, password and email are required")
	}

	// 检查用户是否已存在
	existingUser, _ := s.GetUserByUsername(user.Username)
	if existingUser != nil {
		return errors.New("username already exists")
	}

	// 哈希密码
	user.Password = hashPassword(user.Password)

	// 设置默认值
	if user.Role == "" {
		user.Role = "viewer" // 默认角色为查看者
	}

	if user.Status == "" {
		user.Status = "active" // 默认状态为激活
	}

	// 生成ID
	user.ID = primitive.NewObjectID().Hex()

	// 设置时间戳
	now := time.Now()
	user.CreatedAt = now
	user.UpdatedAt = now

	// 存储用户
	_, err := s.usersCollection.InsertOne(context.Background(), user)
	if err != nil {
		return fmt.Errorf("failed to create user: %v", err)
	}

	return nil
}

// GetUserByID 根据ID获取用户
func (s *MongoUserService) GetUserByID(id string) (*User, error) {
	var user User
	filter := bson.M{"id": id}

	// 查找用户
	err := s.usersCollection.FindOne(context.Background(), filter).Decode(&user)
	if err != nil {
		if err == mongo.ErrNoDocuments {
			return nil, nil // 用户不存在
		}
		return nil, fmt.Errorf("failed to get user: %v", err)
	}

	// 不返回密码
	user.Password = ""

	return &user, nil
}

// GetUserByUsername 根据用户名获取用户
func (s *MongoUserService) GetUserByUsername(username string) (*User, error) {
	var user User
	filter := bson.M{"username": username}

	// 查找用户
	err := s.usersCollection.FindOne(context.Background(), filter).Decode(&user)
	if err != nil {
		if err == mongo.ErrNoDocuments {
			return nil, nil // 用户不存在
		}
		return nil, fmt.Errorf("failed to get user: %v", err)
	}

	return &user, nil
}

// UpdateUser 更新用户信息
func (s *MongoUserService) UpdateUser(user *User) error {
	// 检查用户是否存在
	existingUser, err := s.GetUserByID(user.ID)
	if err != nil {
		return err
	}

	if existingUser == nil {
		return errors.New("user not found")
	}

	// 准备更新数据
	updateData := bson.M{
		"$set": bson.M{
			"email":      user.Email,
			"role":       user.Role,
			"status":     user.Status,
			"updated_at": time.Now(),
		},
	}

	// 如果提供了新密码，则更新密码
	if user.Password != "" {
		updateData["$set"].(bson.M)["password"] = hashPassword(user.Password)
	}

	// 执行更新
	filter := bson.M{"id": user.ID}
	_, err = s.usersCollection.UpdateOne(context.Background(), filter, updateData)
	if err != nil {
		return fmt.Errorf("failed to update user: %v", err)
	}

	return nil
}

// DeleteUser 删除用户
func (s *MongoUserService) DeleteUser(id string) error {
	// 检查用户是否存在
	existingUser, err := s.GetUserByID(id)
	if err != nil {
		return err
	}

	if existingUser == nil {
		return errors.New("user not found")
	}

	// 执行删除
	filter := bson.M{"id": id}
	_, err = s.usersCollection.DeleteOne(context.Background(), filter)
	if err != nil {
		return fmt.Errorf("failed to delete user: %v", err)
	}

	return nil
}

// ListUsers 列出用户（分页）
func (s *MongoUserService) ListUsers(page, pageSize int) ([]*User, int, error) {
	// 计算跳过的记录数
	skip := int64((page - 1) * pageSize)
	limit := int64(pageSize)

	// 设置查询选项
	findOptions := options.Find()
	findOptions.SetSkip(skip)
	findOptions.SetLimit(limit)

	// 查询用户
	cursor, err := s.usersCollection.Find(context.Background(), bson.M{}, findOptions)
	if err != nil {
		return nil, 0, fmt.Errorf("failed to list users: %v", err)
	}
	defer cursor.Close(context.Background())

	// 处理结果
	var users []*User
	for cursor.Next(context.Background()) {
		var user User
		if err := cursor.Decode(&user); err != nil {
			log.Printf("Failed to decode user: %v", err)
			continue
		}
		// 不返回密码
		user.Password = ""
		users = append(users, &user)
	}

	// 获取总数
	count, err := s.usersCollection.CountDocuments(context.Background(), bson.M{})
	if err != nil {
		return nil, 0, fmt.Errorf("failed to count users: %v", err)
	}

	return users, int(count), nil
}

// Authenticate 用户认证
func (s *MongoUserService) Authenticate(username, password string) (*User, error) {
	// 获取用户
	user, err := s.GetUserByUsername(username)
	if err != nil {
		return nil, err
	}

	if user == nil {
		return nil, errors.New("invalid username or password")
	}

	// 验证密码
	if !verifyPassword(password, user.Password) {
		return nil, errors.New("invalid username or password")
	}

	// 检查用户状态
	if user.Status != "active" {
		return nil, errors.New("user account is not active")
	}

	// 不返回密码
	user.Password = ""

	return user, nil
}

// GetRolePermission 获取角色权限
func (s *MongoUserService) GetRolePermission(role string) (*RolePermission, error) {
	var rolePerm RolePermission
	filter := bson.M{"role": role}

	// 查找角色权限
	err := s.rolesCollection.FindOne(context.Background(), filter).Decode(&rolePerm)
	if err != nil {
		if err == mongo.ErrNoDocuments {
			return nil, nil // 角色不存在
		}
		return nil, fmt.Errorf("failed to get role permission: %v", err)
	}

	return &rolePerm, nil
}

// UpdateRolePermission 更新角色权限
func (s *MongoUserService) UpdateRolePermission(rolePerm *RolePermission) error {
	// 准备更新数据
	filter := bson.M{"role": rolePerm.Role}
	update := bson.M{"$set": rolePerm}
	options := options.Update().SetUpsert(true) // 如果不存在则插入

	// 执行更新
	_, err := s.rolesCollection.UpdateOne(context.Background(), filter, update, options)
	if err != nil {
		return fmt.Errorf("failed to update role permission: %v", err)
	}

	return nil
}

// CheckPermission 检查用户是否拥有特定权限
func (s *MongoUserService) CheckPermission(userID, permission string) (bool, error) {
	// 获取用户
	user, err := s.GetUserByID(userID)
	if err != nil {
		return false, err
	}

	if user == nil {
		return false, errors.New("user not found")
	}

	// 获取角色权限
	rolePerm, err := s.GetRolePermission(user.Role)
	if err != nil {
		return false, err
	}

	if rolePerm == nil {
		return false, nil // 角色不存在，没有权限
	}

	// 检查权限
	for _, perm := range rolePerm.Permissions {
		if perm == permission || (strings.HasSuffix(perm, "*") && strings.HasPrefix(permission, perm[:len(perm)-1])) {
			return true, nil
		}
	}

	return false, nil
}

// GetDeviceInfo 获取设备信息
func (s *MongoUserService) GetDeviceInfo(deviceID string) (*DeviceInfo, error) {
	// 从设备数据集合中查找最新的设备信息
	filter := bson.M{"device_id": deviceID}
	sort := bson.D{{Key: "timestamp", Value: -1}}
	options := options.FindOne().SetSort(sort)

	var deviceData bson.M
	err := s.deviceDataCollection.FindOne(context.Background(), filter, options).Decode(&deviceData)
	if err != nil {
		if err == mongo.ErrNoDocuments {
			return nil, nil // 设备不存在
		}
		return nil, fmt.Errorf("failed to get device info: %v", err)
	}

	// 构建DeviceInfo响应
	deviceInfo := &DeviceInfo{
		DeviceID:   deviceID,
		DeviceType: "unknown", // 默认值
		Status:     "online",  // 假设设备是在线的
		Properties: make(map[string]interface{}),
		LastSeen:   time.Now(),
		CreatedAt:  time.Now(),
	}

	// 从最新的设备数据中提取属性
	if data, ok := deviceData["data"].(map[string]interface{}); ok {
		deviceInfo.Properties = data
	}

	// 如果有时间戳信息，更新LastSeen
	if timestamp, ok := deviceData["timestamp"]; ok {
		if timeVal, ok := timestamp.(primitive.DateTime); ok {
			deviceInfo.LastSeen = timeVal.Time()
			deviceInfo.CreatedAt = timeVal.Time()
		}
	}

	return deviceInfo, nil
}

// ListDevices 列出设备（分页）
func (s *MongoUserService) ListDevices(page, pageSize int) ([]*DeviceInfo, int, error) {
	// 使用聚合操作获取唯一的设备ID和每个设备的最新数据
	pipeline := mongo.Pipeline{
		{{"$sort", bson.D{{"timestamp", -1}}}},
		{{"$group", bson.D{{"_id", "$device_id"}, {"data", bson.D{{"$first", "$$ROOT"}}}}}},
		{{"$skip", int64((page - 1) * pageSize)}},
		{{"$limit", int64(pageSize)}},
	}

	cursor, err := s.deviceDataCollection.Aggregate(context.Background(), pipeline)
	if err != nil {
		return nil, 0, fmt.Errorf("failed to list devices: %v", err)
	}
	defer cursor.Close(context.Background())

	// 处理结果
	var devices []*DeviceInfo
	for cursor.Next(context.Background()) {
		var result bson.M
		if err := cursor.Decode(&result); err != nil {
			log.Printf("Failed to decode device: %v", err)
			continue
		}

		// 提取设备数据
		deviceData := result["data"].(map[string]interface{})
		deviceID := deviceData["device_id"].(string)

		// 构建DeviceInfo
		deviceInfo := &DeviceInfo{
			DeviceID:   deviceID,
			DeviceType: "unknown", // 默认值
			Status:     "online",  // 假设设备是在线的
			Properties: make(map[string]interface{}),
			LastSeen:   time.Now(),
			CreatedAt:  time.Now(),
		}

		// 提取属性
		if data, ok := deviceData["data"].(map[string]interface{}); ok {
			deviceInfo.Properties = data
		}

		// 提取时间戳
		if timestamp, ok := deviceData["timestamp"]; ok {
			if timeVal, ok := timestamp.(primitive.DateTime); ok {
				deviceInfo.LastSeen = timeVal.Time()
				deviceInfo.CreatedAt = timeVal.Time()
			}
		}

		devices = append(devices, deviceInfo)
	}

	// 获取唯一设备的总数
	pipelineCount := mongo.Pipeline{
		{{"$group", bson.D{{"_id", "$device_id"}}}},
		{{"$count", "total"}},
	}

	countCursor, err := s.deviceDataCollection.Aggregate(context.Background(), pipelineCount)
	if err != nil {
		return nil, 0, fmt.Errorf("failed to count devices: %v", err)
	}
	defer countCursor.Close(context.Background())

	total := 0
	if countCursor.Next(context.Background()) {
		var countResult bson.M
		if err := countCursor.Decode(&countResult); err == nil {
			if totalVal, ok := countResult["total"].(int32); ok {
				total = int(totalVal)
			}
		}
	}

	return devices, total, nil
}

// GetDeviceData 获取设备数据
func (s *MongoUserService) GetDeviceData(deviceID string, limit int64) ([]*DeviceData, error) {
	// 查询条件
	filter := bson.M{"device_id": deviceID}
	sort := bson.D{{Key: "timestamp", Value: -1}} // 按时间戳降序排序
	options := options.Find().SetSort(sort).SetLimit(limit)

	// 执行查询
	cursor, err := s.deviceDataCollection.Find(context.Background(), filter, options)
	if err != nil {
		return nil, fmt.Errorf("failed to get device data: %v", err)
	}
	defer cursor.Close(context.Background())

	// 处理结果
	var deviceDataList []*DeviceData
	for cursor.Next(context.Background()) {
		var result bson.M
		if err := cursor.Decode(&result); err != nil {
			log.Printf("Failed to decode device data: %v", err)
			continue
		}

		// 构建DeviceData
		deviceData := &DeviceData{
			DeviceID: deviceID,
			Data:     make(map[string]interface{}),
		}

		// 提取数据
		if data, ok := result["data"].(map[string]interface{}); ok {
			deviceData.Data = data
		}

		// 提取时间戳
		if timestamp, ok := result["timestamp"]; ok {
			if timeVal, ok := timestamp.(primitive.DateTime); ok {
				deviceData.Timestamp = timeVal.Time()
			}
		}

		deviceDataList = append(deviceDataList, deviceData)
	}

	return deviceDataList, nil
}

// GetDeviceProperty 获取设备属性
func (s *MongoUserService) GetDeviceProperty(deviceID, property string) (interface{}, error) {
	// 从设备数据集合中查找最新的设备信息
	filter := bson.M{"device_id": deviceID}
	sort := bson.D{{Key: "timestamp", Value: -1}}
	options := options.FindOne().SetSort(sort)

	var deviceData bson.M
	err := s.deviceDataCollection.FindOne(context.Background(), filter, options).Decode(&deviceData)
	if err != nil {
		if err == mongo.ErrNoDocuments {
			return nil, errors.New("device not found")
		}
		return nil, fmt.Errorf("failed to get device data: %v", err)
	}

	// 提取设备数据中的属性
	if data, ok := deviceData["data"].(map[string]interface{}); ok {
		if value, ok := data[property]; ok {
			return value, nil
		}
	}

	return nil, errors.New("property not found")
}

// CreateDevicePropertyConfig 创建设备属性控制配置
func (s *MongoUserService) CreateDevicePropertyConfig(config *DevicePropertyConfig) error {
	// 生成ID
	config.ID = primitive.NewObjectID().Hex()
	config.CreatedAt = time.Now()
	config.UpdatedAt = time.Now()

	// 转换为BSON文档
	doc := bson.M{
		"_id":        config.ID,
		"device_id":  config.DeviceID,
		"property":   config.Property,
		"config":     config.Config,
		"created_at": config.CreatedAt,
		"updated_at": config.UpdatedAt,
	}

	// 插入到MongoDB
	_, err := s.devicePropertyConfigsCollection.InsertOne(context.Background(), doc)
	if err != nil {
		return fmt.Errorf("failed to create device property config: %v", err)
	}

	return nil
}

// GetDevicePropertyConfig 获取单个设备属性控制配置
func (s *MongoUserService) GetDevicePropertyConfig(id string) (*DevicePropertyConfig, error) {
	// 构建查询条件
	filter := bson.M{"_id": id}

	// 查询MongoDB
	var result bson.M
	err := s.devicePropertyConfigsCollection.FindOne(context.Background(), filter).Decode(&result)
	if err != nil {
		if err == mongo.ErrNoDocuments {
			return nil, nil // 配置不存在
		}
		return nil, fmt.Errorf("failed to get device property config: %v", err)
	}

	// 构建返回对象
	config := &DevicePropertyConfig{
		ID:       id,
		DeviceID: result["device_id"].(string),
		Property: result["property"].(string),
		Config:   result["config"].(map[string]interface{}),
	}

	// 解析时间字段
	if createdAt, ok := result["created_at"].(primitive.DateTime); ok {
		config.CreatedAt = createdAt.Time()
	}
	if updatedAt, ok := result["updated_at"].(primitive.DateTime); ok {
		config.UpdatedAt = updatedAt.Time()
	}

	return config, nil
}

// ListDevicePropertyConfigs 列出设备的所有属性控制配置
func (s *MongoUserService) ListDevicePropertyConfigs(deviceID string, page, pageSize int) ([]*DevicePropertyConfig, int, error) {
	// 构建查询条件
	filter := bson.M{"device_id": deviceID}

	// 分页设置
	skip := int64((page - 1) * pageSize)
	limit := int64(pageSize)

	// 查询总数
	count, err := s.devicePropertyConfigsCollection.CountDocuments(context.Background(), filter)
	if err != nil {
		return nil, 0, fmt.Errorf("failed to count device property configs: %v", err)
	}

	// 查询数据
	findOptions := options.Find().SetSkip(skip).SetLimit(limit).SetSort(bson.D{{Key: "created_at", Value: -1}})
	cursor, err := s.devicePropertyConfigsCollection.Find(context.Background(), filter, findOptions)
	if err != nil {
		return nil, 0, fmt.Errorf("failed to list device property configs: %v", err)
	}
	defer cursor.Close(context.Background())

	// 处理结果
	var configs []*DevicePropertyConfig
	for cursor.Next(context.Background()) {
		var result bson.M
		if err := cursor.Decode(&result); err != nil {
			log.Printf("Failed to decode device property config: %v", err)
			continue
		}

		config := &DevicePropertyConfig{
			ID:       result["_id"].(string),
			DeviceID: result["device_id"].(string),
			Property: result["property"].(string),
			Config:   result["config"].(map[string]interface{}),
		}

		// 解析时间字段
		if createdAt, ok := result["created_at"].(primitive.DateTime); ok {
			config.CreatedAt = createdAt.Time()
		}
		if updatedAt, ok := result["updated_at"].(primitive.DateTime); ok {
			config.UpdatedAt = updatedAt.Time()
		}

		configs = append(configs, config)
	}

	return configs, int(count), nil
}

// UpdateDevicePropertyConfig 更新设备属性控制配置
func (s *MongoUserService) UpdateDevicePropertyConfig(config *DevicePropertyConfig) error {
	// 检查配置是否存在
	filter := bson.M{"_id": config.ID}
	var existingConfig bson.M
	err := s.devicePropertyConfigsCollection.FindOne(context.Background(), filter).Decode(&existingConfig)
	if err != nil {
		if err == mongo.ErrNoDocuments {
			return errors.New("config not found")
		}
		return fmt.Errorf("failed to check config existence: %v", err)
	}

	// 更新时间
	config.UpdatedAt = time.Now()

	// 构建更新文档
	update := bson.M{
		"$set": bson.M{
			"config":     config.Config,
			"updated_at": config.UpdatedAt,
		},
	}

	// 执行更新
	_, err = s.devicePropertyConfigsCollection.UpdateOne(context.Background(), filter, update)
	if err != nil {
		return fmt.Errorf("failed to update device property config: %v", err)
	}

	return nil
}

// DeleteDevicePropertyConfig 删除设备属性控制配置
func (s *MongoUserService) DeleteDevicePropertyConfig(id string) error {
	// 构建删除条件
	filter := bson.M{"_id": id}

	// 执行删除
	result, err := s.devicePropertyConfigsCollection.DeleteOne(context.Background(), filter)
	if err != nil {
		return fmt.Errorf("failed to delete device property config: %v", err)
	}

	// 检查是否删除成功
	if result.DeletedCount == 0 {
		return errors.New("config not found")
	}

	return nil
}
